import com.alicp.jetcache.Cache;
import com.alicp.jetcache.MultiLevelCacheBuilder;
import com.alicp.jetcache.embedded.CaffeineCacheBuilder;
import com.alicp.jetcache.redis.RedisCacheBuilder;
import com.alicp.jetcache.redisson.RedissonCacheBuilder;
import com.alicp.jetcache.support.*;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.redisson.Redisson;
import org.redisson.config.Config;
import redis.clients.jedis.JedisPool;

import java.util.HashMap;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * Created on 2016/9/27.
 *
 * @author huangli
 */
public class MultiLevelCacheExample {
    public static void main(String[] args) throws InterruptedException {
//        DefaultCacheMonitor l1CacheMonitor = new DefaultCacheMonitor("OrderCache_L1");
//        DefaultCacheMonitor l2CacheMonitor = new DefaultCacheMonitor("OrderCache_L2");
//        DefaultCacheMonitor orderCacheMonitor = new DefaultCacheMonitor("OrderCache");
//        boolean verboseLog = true;
//        DefaultMetricsManager statLogger = new DefaultMetricsManager(1, TimeUnit.SECONDS, verboseLog);
//        statLogger.add(l1CacheMonitor, l2CacheMonitor, orderCacheMonitor);
//        statLogger.start();

        Cache<Object, Object> l1Cache = CaffeineCacheBuilder.createCaffeineCacheBuilder()
                .limit(100)
                .expireAfterWrite(200, TimeUnit.SECONDS)
                .keyConvertor(Fastjson2KeyConvertor.INSTANCE)
//                .addMonitor(l1CacheMonitor)
                .buildCache();

        GenericObjectPoolConfig pc = new GenericObjectPoolConfig();
        pc.setMinIdle(2);
        pc.setMaxIdle(10);
        pc.setMaxTotal(10);
        JedisPool pool = new JedisPool(pc, "127.0.0.1", 6379);
        Cache<Object, Object> l2Cache = RedisCacheBuilder.createRedisCacheBuilder()
                .jedisPool(pool)
                .keyPrefix("projectD")
                .expireAfterWrite(200, TimeUnit.MINUTES)
                .keyConvertor(Fastjson2KeyConvertor.INSTANCE)
                .valueEncoder(JavaValueEncoder.INSTANCE)
                .valueDecoder(JavaValueDecoder.INSTANCE)
//                .addMonitor(l2CacheMonitor)
                .buildCache();

        Cache<Object, Object> multiLevelCache = MultiLevelCacheBuilder.createMultiLevelCacheBuilder()
                .addCache(l1Cache, l2Cache)
//                .addMonitor(orderCacheMonitor)
                .buildCache();

        multiLevelCache.put("K1", "V1");
        multiLevelCache.put("K2", "V2", 20, TimeUnit.SECONDS);
        System.out.println(multiLevelCache.get("K1"));
        multiLevelCache.remove("K2");

        System.out.println("--------------------------------------------------------------------------------------");
        {
            // 多级缓存穿透后补偿
            l2Cache.put("key1", "l2Cache value");
            System.out.println("key1、l2Cache value = " + l2Cache.get("key1") +
                    ",  key1 l1Cache value = " + l1Cache.get("key1"));
            // 如果可以从多级缓存中获取，则通过checkResultAndFillUpperCache补充下级缓存的数据
            System.out.println("key1 get multiLevelCache = " + multiLevelCache.get("key1"));
            System.out.println("key1 get l1Cache = " + l1Cache.get("key1"));
        }
        System.out.println("--------------------------------------------------------------------------------------");
        {
            // 分级别put时，设置不同的过期时间
            l2Cache.put("key2", "key2 l2Cache value", 3L, TimeUnit.HOURS);
            l1Cache.put("key2", "key2 l1Cache value", 5L, TimeUnit.SECONDS);
            for (int i = 0; i < 6; i++) {
                TimeUnit.SECONDS.sleep(1);
                System.out.println("key2 get multiLevelCache = " + multiLevelCache.get("key2"));
            }
        }
        System.out.println("--------------------------------------------------------------------------------------");

        HashMap<Object, Object> dataMap = new HashMap<>();
        dataMap.put("test1", "1");
        dataMap.put("test2", "2");
        dataMap.put("test3", "3");
        multiLevelCache.putAll(dataMap);

    }

}
